﻿#define  _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <algorithm>
#include <memory.h>
#include <algorithm>

using namespace std;


/*
https://www.papamelon.com/problem/358


有 N 个农场，从 1∼N 标号。其中有一个农场在举行派对。
每个农场都有一头奶牛（除了举行派对的农场）。
农场和农场之间存在单向道路，每条道路都有距离。
所有奶牛都会选择 最短路径 来到派对农场。参加完派对后就各自选择 最短路径 回家。
所有奶牛都会有一个来回总用时（尽它们的努力用时最短），现在让我们求 最大的来回总用时。
数据保证所有奶牛都可以去到派对农场；也能从派对农场回家
数据中可能有重边，自环，但没有负边权
输入
第一行三个整数N(1≤N≤1000),M(1≤M≤100000),X(1≤X≤N)，表示农场数量，道路数量，派对农场编号
接下来 MM 行，每行三个整数 A,B,T(1≤A,B≤N,1≤T≤100)，表示单向道路信息：从 A 走到 B 耗时为 T
输出
一个整数，农场编号，该农场的奶牛去派对农场和回家的耗时总和 最大
样例 1
输入
4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3
输出
10
*/

//反向边 或者 堆优化 dijkstra

const int N = 1010;
const int M = 100010;
int n, m, x;
int a, b, t;
int gra[N][N];
int dist[N];
int vis[N];


int dijkstra(int y) {
	memset(dist, 0x3f, sizeof dist);
	dist[y] = 0;

	//松弛 n-1回
	for (int i = 1; i < n; i++) {
		int t = -1;
		for (int j = 1; j <= n; j++) {
			if (vis[j] == 0 && (t == -1 || dist[t] > dist[j])) {
				t = j;
			}
		}

		for (int j = 1; j <= n; j++) {
			dist[j] = min(dist[j], dist[t] + gra[t][j]);
		}
		vis[t] = 1;;

	}

	if (dist[x] == 0x3f3f3f3f) return -1;
	//返回该点和X的最短路
	return dist[x];
}


int main()
{
	//cin >> n >> m >> x;
	scanf("%d%d%d",&n,&m,&x);
	memset(gra,0x3f,sizeof gra);
	for (int i = 1; i <= n; i++) { gra[i][i] = 0; }
	for (int i = 0; i < m; i++) {
		//cin >> a >> b >> t;
		scanf("%d%d%d",&a,&b,&t);
		gra[a][b] = min(gra[a][b],t);
	}

	dijkstra(x);

	int ansDist[N]; memcpy(ansDist, dist,sizeof ansDist);
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		if (i == x) continue;
		ansDist[i] += dijkstra(i);
		ans = max(ans, ansDist[i]);
	}

	printf("%d\n",ans);

	return 0;
}
 